/*
 *  main.c
 *  
 *
 *  Created by Philip Asare on 12/6/10.
 *  Copyright 2010 __MyCompanyName__. All rights reserved.
 *
 */

#include <nrk.h>
#include <include.h>
#include <ulib.h>
#include <stdio.h>
#include <avr/sleep.h>
#include <hal.h>
#include <rt_link.h>
#include <nrk_error.h>

/* controller tx slots --> base station rx slots */
#define C1

#ifdef C1
#define MY_TX 2
#define MY_RX 5
#endif

#ifdef C2
#define MY_TX 4
#define MY_RX 7
#endif

#ifdef C3
#define MY_TX 6
#define MY_RX 9
#endif

#ifdef C4
#define MY_TX 8
#define MY_RX 11
#endif

#define ALL_RX 3

/* game states and controller tracking */

uint8_t state, player_num;

#define SYNC 1
#define SELECT (1<<1)
#define PREGAME (1<<2)

/* monome helper functions */

#define type(x) (sizeof(x) + PKT_DATA_START)

typedef struct{
	uint8_t player;
} monome_comm_sync_pkt;

monome_comm_sync_pkt sync_pkt_tx, sync_pkt_rx;

inline void monome_set_player_num();
inline void monome_setup_system();
inline void monome_comm_init();

uint8_t tx_len;

/* task setup */

NRK_STK Stack1[NRK_APP_STACKSIZE];
nrk_task_type TaskOne;
void Task1(void);

inline void monome_comm_init();
void nrk_create_taskset();

uint8_t tx_buf[RF_MAX_PAYLOAD_SIZE];
uint8_t rx_buf[RF_MAX_PAYLOAD_SIZE];

int
main ()
{
	uint16_t div;
	nrk_setup_ports();
	nrk_setup_uart(UART_BAUDRATE_115K2);
	
	printf( "Starting up...\r\n" );
	
	
	nrk_init();
	
	nrk_led_clr(0);
	nrk_led_clr(1);
	nrk_led_clr(2);
	nrk_led_clr(3);
	
	nrk_time_set(0,0);
	
	
	rtl_task_config();
	
	nrk_create_taskset ();
	
	nrk_start();
	
	return 0;
}

void Task1()
{
	//uint8_t j, i;
	uint8_t *local_rx_buf;
	uint8_t length,slot;
	int8_t rssi;
	
	monome_comm_init();
	monome_setup_system();
	
	while(!rtl_ready())  nrk_wait_until_next_period(); 
	
	while(1){
		if( rtl_rx_pkt_check()!=0 )
		{
			//nrk_led_set(BLUE_LED);
			local_rx_buf=rtl_rx_pkt_get(&length, &rssi, &slot);
			printf( "Got Packet on slot %d %d: \r\n",slot,length );
			if(length == type(monome_comm_sync_pkt)){
				if(state & SYNC){
					//memcpy(&rx_buf[PKT_DATA_START], &sync_pkt_rx, sizeof(monome_comm_sync_pkt));
					player_num = local_rx_buf[PKT_DATA_START];
					monome_set_player_num();
					rtl_rx_pkt_release();
				}
			}
		}
		if(state & SYNC){
			printf("waiting to sync\r\n");
			while( rtl_tx_pkt_check(MY_TX)!=0 );
			memcpy(&tx_buf[PKT_DATA_START], &sync_pkt_tx, sizeof(monome_comm_sync_pkt));
			tx_len = type(monome_comm_sync_pkt);
			rtl_tx_pkt( tx_buf, tx_len, MY_TX);
			rtl_wait_until_tx_done(MY_TX);
		}
		
		else{
			printf("synced as player %d\r\n", player_num);
		}
		nrk_wait_until_next_period();
	}
}

void
nrk_create_taskset()
{
	
	
	TaskOne.task = Task1;
	TaskOne.Ptos = (void *) &Stack1[NRK_APP_STACKSIZE-1];
	TaskOne.Pbos = (void *) &Stack1[0];
	TaskOne.prio = 2;
	TaskOne.FirstActivation = TRUE;
	TaskOne.Type = BASIC_TASK;
	TaskOne.SchType = PREEMPTIVE;
	TaskOne.period.secs = 1;
	TaskOne.period.nano_secs = 0;
	TaskOne.cpu_reserve.secs = 0;
	TaskOne.cpu_reserve.nano_secs = 200*NANOS_PER_MS;
	TaskOne.offset.secs = 0;
	TaskOne.offset.nano_secs= 0;
	nrk_activate_task (&TaskOne);
	
	
	printf ("Create done\r\n");
}

inline void monome_comm_init(){
	rtl_init (RTL_MOBILE);
	
	/* rx schedules */
	rtl_set_schedule( RTL_RX, MY_RX, 1 );
	rtl_set_schedule( RTL_RX, ALL_RX, 1 );

	/* tx schedules */
	rtl_set_schedule( RTL_TX, MY_TX, 1 );
	
	rtl_start();
	rtl_rx_pkt_set_buffer(rx_buf, RF_MAX_PAYLOAD_SIZE);
}

inline void monome_setup_system(){
	state = 0 | SYNC;
	player_num = -1;
	sync_pkt_tx.player = -1;
	
}

inline void monome_set_player_num(){
	printf("setting player\r\n");
	//player_num = sync_pkt_rx.player;
	printf("player number: %d\r\n", player_num);
	switch (player_num) {
		case 0:
			nrk_led_set(RED_LED);
			break;
		case 1:
			nrk_led_set(GREEN_LED);
			break;
		case 2:
			nrk_led_set(RED_LED); nrk_led_set(GREEN_LED);
			break;
		case 3:
			nrk_led_set(BLUE_LED);
			break;
		default:
			break;
	}
	state = 0 | SELECT;
}
